#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <endianhelper.h>

static bool _le = false;

static bool _has_init = false;

bool endian_is_le()
{
    if (!_has_init) {
        _has_init = true;

        char b[2] = { 1, 2 };
        if (*(short *)b == 0x0201)
            _le = true;
        else
            _le = false;
    }
    return _le;
}

void endian_stom_le(unsigned short i, void *p)
{
    if (endian_is_le()) {
        *(unsigned short *) p = i;
    }
    else {
        ((unsigned char *) p)[0] = ((unsigned char *) &i)[1];
        ((unsigned char *) p)[1] = ((unsigned char *) &i)[0];
    }
}

short endian_mtos_le(void *p)
{
    if (endian_is_le()) {
        return *(short *) p;
    }
    else {
        unsigned char b[2];
        b[0] = ((unsigned char *) p)[1];
        b[1] = ((unsigned char *) p)[0];
        return *(short *)b;
    }
}

void endian_itom_le(unsigned int i, void *p)
{
    if (endian_is_le()) {
        *(unsigned int *) p = i;
    }
    else {
        ((unsigned char *) p)[0] = ((unsigned char *) &i)[3];
        ((unsigned char *) p)[1] = ((unsigned char *) &i)[2];
        ((unsigned char *) p)[2] = ((unsigned char *) &i)[1];
        ((unsigned char *) p)[3] = ((unsigned char *) &i)[0];
    }
}

int  endian_mtoi_le(void *p)
{
    if (endian_is_le()) {
        return *(int *) p;
    }
    else {
        unsigned char b[4];
        b[0] = ((unsigned char *) p)[3];
        b[1] = ((unsigned char *) p)[2];
        b[2] = ((unsigned char *) p)[1];
        b[3] = ((unsigned char *) p)[0];
        return *(int *)b;
    }
}

void endian_lltom_le(Uint64 i, void *p)
{
    if (endian_is_le()) {
        *(Uint64 *) p = i;
    }
    else {
        ((unsigned char *) p)[0] = ((unsigned char *) &i)[7];
        ((unsigned char *) p)[1] = ((unsigned char *) &i)[6];
        ((unsigned char *) p)[2] = ((unsigned char *) &i)[5];
        ((unsigned char *) p)[3] = ((unsigned char *) &i)[4];
        ((unsigned char *) p)[4] = ((unsigned char *) &i)[3];
        ((unsigned char *) p)[5] = ((unsigned char *) &i)[2];
        ((unsigned char *) p)[6] = ((unsigned char *) &i)[1];
        ((unsigned char *) p)[7] = ((unsigned char *) &i)[0];
    }
}

Uint64 endian_mtoll_le(void *p)
{
    if (endian_is_le()) {
        return *(Uint64 *) p;
    }
    else {
        unsigned char b[8];
        b[0] = ((unsigned char *) p)[7];
        b[1] = ((unsigned char *) p)[6];
        b[2] = ((unsigned char *) p)[5];
        b[3] = ((unsigned char *) p)[4];
        b[4] = ((unsigned char *) p)[3];
        b[5] = ((unsigned char *) p)[2];
        b[6] = ((unsigned char *) p)[1];
        b[7] = ((unsigned char *) p)[0];
        return *(Uint64 *)b;
    }
}
